// 在这里定义和用户相关的路由处理函数，供 /router/userInfo.js 模块进行调用

// 导入数据库操作模块
const db = require('../db/index');
// 导入 bcryptjs 模块
const bcrypt = require('bcryptjs');

// 导入需要的验证规则对象
const { validateUserRegister } = require('../schema/user');

// 用这个包来生成 Token 字符串
const jwt = require('jsonwebtoken');
// 导入配置文件
const config = require('../config');

// 注册用户的处理函数
exports.regiser = async (req, res, next) => {
    // 1.接受表单提交的数据
    const userInfo = req.body;

    // 2.判断数据是否合法 用joi第三方模块判断
    try {
        await validateUserRegister(userInfo);
    } catch (err) {
        // 异步方法只能用 next() 方法触发错误处理中间件 next()只能传递字符串
        return next(err.message);
    }
    // 3.定义 SQL 语句：
    const sqlSelect = 'SELECT * FROM users WHERE username =? ';
    // 4.执行 SQL 语句并根据结果判断用户名是否被占用
    db.query(sqlSelect, userInfo.username, function (err, results) {
        // 执行 SQL 语句失败
        if (err) {
            return res.cc(err);
        }
        // 用户名被占用
        if (results.length > 0) {
            return res.cc('用户名被占用，请更换其他用户名！', 400, null);
        }
        // 用户名可用,对用户的密码,进行 bcrype 加密，返回值是加密之后的密码字符串
        userInfo.password = bcrypt.hashSync(userInfo.password, 10)

        // 定义插入用户的 SQL 语句
        const sqlInsert = 'INSERT INTO users (username,password) values (?,?)';
        // 调用 db.query() 执行 SQL 语句，插入新用户
        db.query(sqlInsert, [userInfo.username, userInfo.password], (err, results) => {
            // 执行 SQL 语句失败
            if (err) {
                return res.cc(err, 400, null);
            }
            // SQL 语句执行成功，但影响行数不为 1
            if (results.affectedRows !== 1) {
                return res.cc('注册用户失败，请稍后再试！', 400, null);
            }
            // 注册成功
            return res.cc('注册成功！', 201, null);
        });
    });
};

// 登录的处理函数
exports.login = (req, res) => {
    // 接受表单提交的登录数据
    const userReqInfo = req.body;
    // 定义 SQL 语句
    const sql = 'SELECT * FROM users WHERE username =? ';
    // 执行 SQL 语句，查询用户的数据
    db.query(sql, userReqInfo.username, function (err, results) {
        // 执行 SQL 语句失败
        if (err) return res.cc(err);
        // 执行 SQL 语句成功，但是查询到数据条数不等于 1 说明用户名输入错误
        if (results.length !== 1) return res.cc('用户名输入错误！', 400, null);

        // 获取数据成功
        const userResInfo = results[0];
        // 判断密码是否正确
        // 拿着用户输入的密码,和数据库中存储的密码进行对比
        const compareResult = bcrypt.compareSync(userReqInfo.password, userResInfo.password);

        // 如果对比的结果等于 false, 则证明用户输入的密码错误
        if (!compareResult) {
            return res.cc('密码输入错误！', 400, null);
        }
        // 登录成功，在服务器端生成 Token 字符串
        // 剔除完毕之后，user 中只保留了用户的 id, username, nickname, email 这四个属性的值
        const user = { ...userResInfo, password: '', user_pic: '' };

        // 将用户信息对象加密成 Token 字符串
        const tokenStr = jwt.sign(user, config.jwtSecretKey, {
            expiresIn: config.expiresIn
        });
        // 将生成的 Token 字符串响应给客户端
        // 为了方便客户端使用 Token，在服务器端直接拼接上 Bearer 的前缀
        userResInfo.token = 'Bearer ' + tokenStr;
        delete userResInfo.password;
        res.cc('登录成功！', 200, userResInfo)
    });
};
